package com.example.socket.schema;

import com.example.socket.filter.session.SessionManager;
import com.example.socket.server.ExecutorConfig;
import com.example.socket.server.GameServer;
import com.example.socket.server.ServerConfig;
import com.example.socket.thread.NamedThreadFactory;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;

import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;

/**
 * @author frank
 */
public class SocketInitializer implements ApplicationListener<ApplicationEvent> {

    private static final Logger logger = LoggerFactory.getLogger(SocketInitializer.class);


    private ServerConfig config;

    private SessionManager sessionManager;

    private ExecutorService executor;

    private EventLoopGroup workerGroup;

    private GameServer gameServer;

    private boolean started;

    @PostConstruct
    protected void initialize() {
        // 线程池
        int workers = Runtime.getRuntime().availableProcessors() / 2;
        workers = Math.max(workers, 1);
        workerGroup = new NioEventLoopGroup(workers, new NamedThreadFactory("服务器NIO线程"));
        // 设置处理线程池
        ExecutorConfig executorConfig = config.getExecutorConfig();
        executor = executorConfig.build();
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {

        if (event instanceof ContextRefreshedEvent) {
            //判断是否重复启动，或者是不需要开机启动
            if (!config.isAutoStart() || started) {
                return;
            }
            start();
        } else if (event instanceof ContextClosedEvent) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            if (started) {
                started = false;
                destroy();
            }
        }
    }

    /** 关闭服务器 */
    public void destroy() {
        if (gameServer != null) {
            gameServer.destroy();
        }
        workerGroup.shutdownGracefully();
        if (executor != null) {
            executor.shutdownNow();
        }
    }

    /** 开启服务器 */
    public void start() {
        if (logger.isDebugEnabled()) {
            logger.debug("开启服务器");
        }
        if (gameServer != null) {
            started = true;
            gameServer.start(config, workerGroup, executor, sessionManager);
        }
    }

    // Getter and Setter ...

    public void setConfig(ServerConfig config) {
        this.config = config;
    }

    public void setSessionManager(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public void setGameServer(GameServer gameServer) {
        this.gameServer = gameServer;
    }

}
